home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / dev / c / flash-0.4.3.lha / flash-0.4.3 / Lib / bitmap.cc < prev    next >
C/C++ Source or Header  |  1999-02-21  |  11KB  |  553 lines

  1. /////////////////////////////////////////////////////////////
  2. // Flash Plugin and Player
  3. // Copyright (C) 1998 Olivier Debon
  4. // 
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9. // 
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14. // 
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18. // 
  19. ///////////////////////////////////////////////////////////////
  20. //  Author : Olivier Debon  <odebon@club-internet.fr>
  21. //  
  22.  
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <sys/types.h>
  27. #include <setjmp.h>
  28. #include "bitmap.h"
  29. #include "graphic.h"
  30.  
  31. static char *rcsid = "$Id: bitmap.cc,v 1.11 1999/01/31 20:09:10 olivier Exp $";
  32.  
  33. static unsigned char *inputData;
  34.  
  35. extern "C" {
  36. #include "Jpeg/jpeglib.h"
  37. };
  38.  
  39. extern "C" {
  40. #include "Zlib/zlib.h"
  41. };
  42.  
  43. // Class variables
  44.  
  45. int Bitmap::haveTables = 0;
  46.  
  47. struct jpeg_decompress_struct Bitmap::jpegObject;
  48.  
  49. struct jpeg_source_mgr Bitmap::jpegSourceManager;
  50.  
  51. MyErrorHandler Bitmap::jpegErrorMgr;
  52.  
  53. Bitmap::Bitmap(long id, int level) : Character(BitmapType, id )
  54. {
  55.     pixels = 0;
  56.     colormap = 0;
  57.     nbColors = 0;
  58.     defLevel = level;
  59. }
  60.  
  61. Bitmap::~Bitmap()
  62. {
  63.     if (pixels) {
  64.         free(pixels);
  65.     }
  66.     if (colormap)
  67.     {
  68.         free(colormap);
  69.     }
  70. }
  71.  
  72. static void errorExit(j_common_ptr info)
  73. {
  74.     (*info->err->output_message) (info);
  75.     longjmp(((MyErrorHandler *)info->err)->setjmp_buffer, 1);
  76. }
  77.  
  78. // Methods for Source data manager
  79. static void initSource(struct jpeg_decompress_struct *cInfo)
  80. {
  81.     cInfo->src->bytes_in_buffer = 0;
  82. }
  83.  
  84. static boolean fillInputBuffer(struct jpeg_decompress_struct *cInfo)
  85. {
  86.     cInfo->src->next_input_byte = inputData;
  87.     cInfo->src->bytes_in_buffer = 1;
  88.     inputData++;
  89.  
  90.     return 1;
  91. }
  92.  
  93. static void skipInputData(struct jpeg_decompress_struct *cInfo, long count)
  94. {
  95.     cInfo->src->bytes_in_buffer = 0;
  96.     inputData += count;
  97. }
  98.  
  99. static boolean resyncToRestart(struct jpeg_decompress_struct *cInfo, int desired)
  100. {
  101.     return jpeg_resync_to_restart(cInfo, desired);
  102. }
  103.  
  104. static void termSource(struct jpeg_decompress_struct *cInfo)
  105. {
  106. }
  107.  
  108. long Bitmap::getWidth()
  109. {
  110.     return width;
  111. }
  112.  
  113. long Bitmap::getHeight()
  114. {
  115.     return height;
  116. }
  117.  
  118. Color *
  119. Bitmap::getColormap(long *n) {
  120.        if (n) *n = nbColors;
  121.        return colormap;
  122. }
  123.  
  124. unsigned char *
  125. Bitmap::getPixels()
  126. {
  127.        return pixels;
  128. }
  129.  
  130. SwfPix *
  131. Bitmap::getImage(GraphicDevice *gd, Matrix *mat, Cxform *cxform)
  132. {
  133.     float xFactor, yFactor;
  134.     long w,h;
  135.     long x,y;
  136.     SwfPix *pix;
  137.     unsigned char *p;
  138.     unsigned char *cLine;
  139.     long pixel;
  140.     char *line;
  141.     long incrLine;
  142.     long n;
  143.     long X,DX;
  144.     Color *cmap;
  145.  
  146.     if (pixels == 0) return 0;
  147.  
  148.     xFactor = mat->a / 20.0;
  149.     yFactor = mat->d / 20.0;
  150.  
  151.     // Not supported although it could be simple
  152.     if (xFactor < 0 || yFactor < 0) return 0;
  153.  
  154.     w = (long)(xFactor * width);
  155.     h = (long)(yFactor * height);
  156.  
  157.     cmap = gd->getColormap(colormap, nbColors, cxform);
  158.  
  159.     pix = gd->createSwfPix(w,h);
  160.  
  161.     line = pix->data;
  162.     incrLine = pix->bpl;
  163.  
  164.     DX = (long)(65536.0/xFactor);
  165.  
  166.     if (gd->bpp == 2) {
  167.         for(y=0; y < h; y++)
  168.         {
  169.             short *ptr;
  170.  
  171.             ptr = (short *)line;
  172.             cLine = pixels+(long)(y/yFactor)*width;
  173.             X = 0;
  174.             for(x=0; x < w; x++)
  175.             {
  176.                 p = cLine+(X>>16);
  177.                 X+=DX;
  178.                 *ptr = cmap[*p].pixel;
  179.                 ptr++;
  180.             }
  181.             line += incrLine;
  182.         }
  183.     } else
  184.     if (gd->bpp == 4) {
  185.         for(y=0; y < h; y++)
  186.         {
  187.             long *ptr;
  188.  
  189.             ptr = (long *)line;
  190.             cLine = pixels+(long)(y/yFactor)*width;
  191.             X = 0;
  192.             for(x=0; x < w; x++)
  193.             {
  194.                 p = cLine+(X>>16);
  195.                 X+=DX;
  196.                 *ptr = cmap[*p].pixel;
  197.                 ptr++;
  198.             }
  199.             line += incrLine;
  200.         }
  201.     } else
  202.     if (gd->bpp == 1) {
  203.         for(y=0; y < h; y++)
  204.         {
  205.             char *ptr;
  206.  
  207.             ptr = (char *)line;
  208.             cLine = pixels+(long)(y/yFactor)*width;
  209.             X = 0;
  210.             for(x=0; x < w; x++)
  211.             {
  212.                 p = cLine+(X>>16);
  213.                 X+=DX;
  214.                 *ptr = cmap[*p].pixel;
  215.                 ptr++;
  216.             }
  217.             line += incrLine;
  218.         }
  219.     }
  220.  
  221.     free(cmap);
  222.  
  223.     return pix;
  224. }
  225.  
  226. // Read Tables and Compressed data to produce an image
  227.  
  228. int
  229. Bitmap::buildFromJpegInterchangeData(unsigned char *stream)
  230. {
  231.     struct jpeg_decompress_struct cInfo;
  232.     struct jpeg_source_mgr mySrcMgr;
  233.     MyErrorHandler errorMgr;
  234.     JSAMPARRAY buffer;
  235.     unsigned char *ptrPix;
  236.     int stride;
  237.     long n;
  238.  
  239.     // Setup error handler
  240.     cInfo.err = jpeg_std_error(&errorMgr.pub);
  241.     errorMgr.pub.error_exit = errorExit;
  242.  
  243.     if (setjmp(errorMgr.setjmp_buffer)) {
  244.         // JPEG data Error
  245.         jpeg_destroy_decompress(&cInfo);
  246.         return -1;
  247.     }
  248.  
  249.     // Set current stream pointer to stream
  250.     inputData = stream;
  251.  
  252.     // Here it's Ok
  253.  
  254.     jpeg_create_decompress(&cInfo);
  255.  
  256.     // Setup source manager structure
  257.     mySrcMgr.init_source = initSource;
  258.     mySrcMgr.fill_input_buffer = fillInputBuffer;
  259.     mySrcMgr.skip_input_data = skipInputData;
  260.     mySrcMgr.resync_to_restart = resyncToRestart;
  261.     mySrcMgr.term_source = termSource;
  262.  
  263.     // Set default source manager
  264.     cInfo.src = &mySrcMgr;
  265.  
  266.     jpeg_read_header(&cInfo, FALSE);
  267.  
  268.     jpeg_read_header(&cInfo, TRUE);
  269.     cInfo.quantize_colors = TRUE;    // Create colormapped image
  270.  
  271.     jpeg_start_decompress(&cInfo);
  272.  
  273.     // Set objet dimensions
  274.     height = cInfo.output_height;
  275.     width = cInfo.output_width;
  276.     pixels = (unsigned char *)malloc(height*width);
  277.     ptrPix = pixels;
  278.  
  279.     stride = cInfo.output_width * cInfo.output_components;
  280.  
  281.     buffer = (*cInfo.mem->alloc_sarray) ((j_common_ptr) &cInfo, JPOOL_IMAGE, stride, 1);
  282.  
  283.     while (cInfo.output_scanline < cInfo.output_height) {
  284.  
  285.         jpeg_read_scanlines(&cInfo, buffer, 1);
  286.  
  287.         memcpy(ptrPix,buffer[0],stride);
  288.  
  289.         ptrPix+= stride;
  290.     }
  291.  
  292.     colormap = new Color[cInfo.actual_number_of_colors];
  293.     nbColors = cInfo.actual_number_of_colors;
  294.  
  295.     for(n=0; n < nbColors; n++)
  296.     {
  297.         colormap[n].red = cInfo.colormap[0][n];
  298.         colormap[n].green = cInfo.colormap[1][n];
  299.         colormap[n].blue = cInfo.colormap[2][n];
  300.     }
  301.  
  302.     jpeg_finish_decompress(&cInfo);
  303.     jpeg_destroy_decompress(&cInfo);
  304.  
  305.     return 0;
  306. }
  307.  
  308. // Read JPEG image using pre-loaded Tables
  309.  
  310. int
  311. Bitmap::buildFromJpegAbbreviatedData(unsigned char *stream)
  312. {
  313.     JSAMPROW buffer[1];
  314.     unsigned char *ptrPix;
  315.     int stride;
  316.     long n;
  317.     int status;
  318.  
  319.     // Set current stream pointer to stream
  320.     inputData = stream;
  321.  
  322.     // Error handler
  323.     if (setjmp(jpegErrorMgr.setjmp_buffer)) {
  324.         // JPEG data Error
  325.         jpeg_destroy_decompress(&jpegObject);
  326.         return -1;
  327.     }
  328.  
  329.     // Here it's ok
  330.  
  331.     jpeg_read_header(&jpegObject, TRUE);
  332.     jpegObject.quantize_colors = TRUE;    // Create colormapped image
  333.  
  334.     jpeg_start_decompress(&jpegObject);
  335.  
  336.     // Set objet dimensions
  337.     height = jpegObject.output_height;
  338.     width = jpegObject.output_width;
  339.     pixels = (unsigned char *)malloc(height*width);
  340.     ptrPix = pixels;
  341.  
  342.     stride = jpegObject.output_width * jpegObject.output_components;
  343.  
  344.     buffer[0] = (JSAMPROW)malloc(stride);
  345.  
  346.     while (jpegObject.output_scanline < jpegObject.output_height) {
  347.  
  348.         status = jpeg_read_scanlines(&jpegObject, buffer, 1);
  349.  
  350.         memcpy(ptrPix,buffer[0],stride);
  351.  
  352.         ptrPix+= stride;
  353.     }
  354.  
  355.     colormap = new Color[jpegObject.actual_number_of_colors];
  356.     nbColors = jpegObject.actual_number_of_colors;
  357.  
  358.     for(n=0; n < nbColors; n++)
  359.     {
  360.         colormap[n].red = jpegObject.colormap[0][n];
  361.         colormap[n].green = jpegObject.colormap[1][n];
  362.         colormap[n].blue = jpegObject.colormap[2][n];
  363.     }
  364.  
  365.     status = jpeg_finish_decompress(&jpegObject);
  366.  
  367.     return 0;
  368. }
  369.  
  370. // Just init JPEG object and read JPEG Tables
  371.  
  372. int
  373. Bitmap::readJpegTables(unsigned char *stream)
  374. {
  375.     if (haveTables) {
  376.         //Error, it has already been initialized
  377.         return -1;
  378.     }
  379.  
  380.     // Setup error handler
  381.     jpegObject.err = jpeg_std_error(&jpegErrorMgr.pub);
  382.     jpegErrorMgr.pub.error_exit = errorExit;
  383.  
  384.     if (setjmp(jpegErrorMgr.setjmp_buffer)) {
  385.         // JPEG data Error
  386.         jpeg_destroy_decompress(&jpegObject);
  387.         return -1;
  388.     }
  389.  
  390.     // Set current stream pointer to stream
  391.     inputData = stream;
  392.  
  393.     // Here it's Ok
  394.  
  395.     jpeg_create_decompress(&jpegObject);
  396.  
  397.     // Setup source manager structure
  398.     jpegSourceManager.init_source = initSource;
  399.     jpegSourceManager.fill_input_buffer = fillInputBuffer;
  400.     jpegSourceManager.skip_input_data = skipInputData;
  401.     jpegSourceManager.resync_to_restart = resyncToRestart;
  402.     jpegSourceManager.term_source = termSource;
  403.  
  404.     // Set default source manager
  405.     jpegObject.src = &jpegSourceManager;
  406.  
  407.     jpeg_read_header(&jpegObject, FALSE);
  408.  
  409.     return 0;
  410. }
  411.  
  412. int Bitmap::buildFromZlibData(unsigned char *buffer, int width, int height, int format, int tableSize)
  413. {
  414.     z_stream    stream;
  415.     int        status;
  416.     unsigned char  *data;
  417.  
  418.     this->width = width;
  419.     this->height = height;
  420.  
  421.     stream.next_in = buffer;
  422.     stream.avail_in = 1;
  423.     stream.zalloc = Z_NULL;
  424.     stream.zfree = Z_NULL;
  425.  
  426.     tableSize++;
  427.  
  428.     // Uncompress Color Table
  429.     if (format == 3) {
  430.         unsigned char *colorTable;
  431.         long n;
  432.  
  433.         // Ajust width for 32 bit padding
  434.         width = (width+3)/4*4;
  435.         this->width = width;
  436.  
  437.         depth = 1;
  438.         colorTable = new unsigned char[tableSize*3];
  439.  
  440.         stream.next_out = colorTable;
  441.         stream.avail_out = tableSize*3;
  442.  
  443.         inflateInit(&stream);
  444.  
  445.         while (1) {
  446.             status = inflate(&stream, Z_SYNC_FLUSH);
  447.             if (status == Z_STREAM_END) {
  448.                     break;
  449.             }
  450.             if (status != Z_OK) {
  451.                 printf("Zlib cmap error : %s\n", stream.msg);
  452.                 return 1;
  453.             }
  454.             stream.avail_in = 1;
  455.             // Colormap if full
  456.             if (stream.avail_out == 0) {
  457.                 break;
  458.             }
  459.         }
  460.  
  461.         nbColors = tableSize;
  462.  
  463.         colormap = (Color *)malloc(nbColors*sizeof(Color));
  464.  
  465.         for(n=0; n < nbColors; n++) {
  466.             colormap[n].red = colorTable[n*3+0];
  467.             colormap[n].green = colorTable[n*3+1];
  468.             colormap[n].blue = colorTable[n*3+2];
  469.         }
  470.  
  471.         delete colorTable;
  472.  
  473.     } else if (format == 4) {
  474.         depth = 2;
  475.     } else if (format == 5) {
  476.         depth = 4;
  477.     }
  478.  
  479.     data = new unsigned char[depth*width*height];
  480.  
  481.     stream.next_out = data;
  482.     stream.avail_out = depth*width*height;
  483.  
  484.     if (format != 3) {
  485.         status = inflateInit(&stream);
  486.     }
  487.  
  488.     while (1) {
  489.         status = inflate(&stream, Z_SYNC_FLUSH) ;
  490.         if (status == Z_STREAM_END) {
  491.                 break;
  492.         }
  493.         if (status != Z_OK) {
  494.             printf("Zlib data error : %s\n", stream.msg);
  495.             return 1;
  496.         }
  497.         stream.avail_in = 1;
  498.     }
  499.  
  500.     inflateEnd(&stream);
  501.  
  502.     pixels = (unsigned char *)malloc(height*width);
  503.  
  504.     if (format != 3) {
  505.         int n,c;
  506.         unsigned char r,g,b,a;
  507.         unsigned char *ptr;
  508.  
  509.         nbColors = 0;
  510.         colormap = (Color *)calloc(256,sizeof(Color));
  511.         ptr = pixels;
  512.         
  513.         for(n=0; n < width*height*depth; n+=depth,ptr++) {
  514.             switch (format) {
  515.                 case 4:
  516.                     break;
  517.                 case 5:
  518.                     a = data[n];
  519.                     // Reduce color dynamic range
  520.                     r = data[n+1]&0xe0;
  521.                     g = data[n+2]&0xe0;
  522.                     b = data[n+3]&0xe0;
  523.                     break;
  524.             }
  525.             for(c=0; c < nbColors; c++) {
  526.                 if (r == colormap[c].red
  527.                 &&  g == colormap[c].green
  528.                 &&  b == colormap[c].blue) {
  529.                     *ptr = c;
  530.                     break;
  531.                 }
  532.             }
  533.             if (c == nbColors) {
  534.                 if (nbColors == 256) continue;
  535.                 nbColors++;
  536.                 if (nbColors == 256) {
  537.                     //printf("Colormap entries exhausted. After %d scanned pixels\n", n/4);
  538.                 }
  539.                 colormap[c].alpha = a;
  540.                 colormap[c].red   = r;
  541.                 colormap[c].green = g;
  542.                 colormap[c].blue  = b;
  543.                 *ptr = c;
  544.             }
  545.         }
  546.     } else {
  547.         memcpy(pixels, data, width*height);
  548.     }
  549.  
  550.     delete data;
  551.     return 0;
  552. }
  553.